package com.filldream.fastboot.core.manager;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.filldream.fastboot.common.constant.FinalStr;
import com.filldream.fastboot.base.entity.WxConfig;
import com.filldream.fastboot.common.exception.GlobalException;
import com.filldream.fastboot.common.entity.ErrorCode;
import com.filldream.fastboot.common.util.UrlUtil;
import com.filldream.fastboot.common.util.WxUtil;
import com.filldream.fastboot.core.cache.CacheMap;
import com.filldream.fastboot.core.cache.CacheObj;
import com.filldream.fastboot.core.cache.CacheUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.security.MessageDigest;
import java.util.HashMap;
import java.util.Map;

/**
 * @author RickSun && iFillDream
 * @version 1.0
 * @data 2020-06-01 18:59
 * @description 微信JsSDK管理
 */
@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class WxJsSDKManager {


    @Autowired
    private WxConfigManager wxConfigManager;

    /**
     * 获取微信JsSdk
     * @param url
     * @param wxAppid
     * @return
     */
    public Map<String, String> getJsSdkConfig(String url, String wxAppid){
        WxConfig wxConfig = wxConfigManager.selectByAppId(wxAppid);

        Map<String, String> res = new HashMap<String, String>();
        try {
            String jsapiTicket = postTicket(wxConfig);
            String nonceStr = WxUtil.createNonceStr();
            String timestamp  = WxUtil.createTimestamp();
            //注意这里参数名必须全部小写，且必须有序
            String string1 = "jsapi_ticket=" + jsapiTicket + "&noncestr=" + nonceStr + "&timestamp=" + timestamp + "&url=" + url;
            MessageDigest crypt = MessageDigest.getInstance("SHA-1");
            crypt.reset();
            crypt.update(string1.getBytes("UTF-8"));
            String signature = WxUtil.byteToHex(crypt.digest());

            res.put("appId", wxConfig.getAppId());
            res.put("url", url);
            res.put("timestamp", timestamp);
            res.put("nonceStr", nonceStr);
            res.put("signature", signature);
            log.info("获取JsSDK:{} ticket:{}", res , jsapiTicket);
        } catch (Exception e) {
            new GlobalException(ErrorCode.BASE_ERR.reMsg("JsSDKConfig获取失败"),e);
        }
        return res;
    }

    /**
     * 调用ticket
     * @param wxConfig
     * @return
     * @throws Exception
     */
    private String postTicket(WxConfig wxConfig) throws Exception {
        String accessToken = wxConfig.getAccessToken();

        String tickt = getTicket(wxConfig.getAppId());
        if(StringUtils.isNotBlank(tickt)){
            return tickt;
        }

        String content = UrlUtil.doGet(String.format(FinalStr.JSAPI_TICKET_URL, accessToken), null);
        if (content == null) {
            throw new GlobalException(ErrorCode.BASE_ERR.reMsg("JsApiTicket获取失败"));
        }else if(content.indexOf("access_token expired") > 0 || content.contains("nvalid or not latest")){
            //刷新token
            wxConfig = wxConfigManager.refreshAccessToken(wxConfig.getId());
            content = UrlUtil.doGet(String.format(FinalStr.JSAPI_TICKET_URL, wxConfig.getAccessToken()), null);
        }
        ObjectMapper mapper = new ObjectMapper();
        Map<String, Object> map = mapper.readValue(content, Map.class);
        String jsapiTicket = (String) map.get("ticket");
        if(jsapiTicket == null){
            throw new GlobalException(ErrorCode.BASE_ERR.reMsg("JsApiTicket获取失败，content："+content));
        }
        log.info("获取ticket:{}",jsapiTicket);
        return addTicket(wxConfig.getAppId(),jsapiTicket);
    }

    public String getTicket(String appid){
        CacheObj<Map> cache = CacheUtil.getCache(CacheMap.WX_TICKET_DETAIL, Map.class, appid);
        if( cache.getData() != null && !cache.getData().isEmpty() ){
            return (String) cache.getData().get("ticket");
        }
        return  "";
    }

    public String addTicket(String appid,String ticket){
        CacheObj<Map> cache = CacheUtil.getCache(CacheMap.WX_TICKET_DETAIL, Map.class, appid);
        Map<String,String> map = new HashMap<>();
        map.put("ticket",ticket);
        CacheUtil.cacheObj(cache.getCacheKey(),map,7120);
        return  ticket;
    }




}
